//////////////////////////////////////////////////////////////////////
//
// NO_Pointer.h
//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
#ifndef RCRESPTR_H_
#define RCRESPTR_H_

//////////////////////////////////////////////////////////////////////////
class NO_IPtrHelp
{
public:
	//////////////////////////////////////////////////////////////////////////
	NO_IPtrHelp(void* address, NO_UInt32 ref):address(address),ref(ref){}
	virtual ~NO_IPtrHelp(){}

	//////////////////////////////////////////////////////////////////////////
	void* address;
	NO_UInt32 ref;
};

//////////////////////////////////////////////////////////////////////////
template<class Type>
class NO_PtrHelp : public NO_IPtrHelp
{
public:
	//////////////////////////////////////////////////////////////////////////
	NO_PtrHelp(Type* address, NO_UInt32 ref):NO_IPtrHelp(address,ref){}

	//////////////////////////////////////////////////////////////////////////
	virtual ~NO_PtrHelp()
	{
		if (address)
		{
			Type* ptr = static_cast<Type*>(address);
			delete ptr;
		}
	}
};

//////////////////////////////////////////////////////////////////////
//class NO_Pointer 
//////////////////////////////////////////////////////////////////////////
template <class Type>
class NO_Pointer
{
public:
	//////////////////////////////////////////////////////////////////////
	typedef NO_Pointer<Type>	Pointer;
	typedef Type*				TPointer;
	typedef Type&				TReference;
	
	//////////////////////////////////////////////////////////////////////
	// con/destructor
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_Pointer(TPointer ptr=0) : ptr(ptr),ext(new NO_PtrHelp<Type>(ptr,1)) 
	{

	}
	explicit NO_Pointer(TPointer ptr, NO_IPtrHelp* ext) : ptr(ptr),ext(ext) {++(ext->ref);}

	//////////////////////////////////////////////////////////////////////
	~NO_Pointer(void)
	{
		if((--(ext->ref))==0)
		{
			delete ext;
		}
	}
	
	//////////////////////////////////////////////////////////////////////
	NO_Pointer(const Pointer& rhs)
	{
		ptr = rhs.ptr;
		ext = rhs.ext;
		++(ext->ref);
	}

	//////////////////////////////////////////////////////////////////////
	// operator
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	Pointer& operator= (const Pointer& rhs)		
	{
		if(ptr==rhs.ptr){return *this;}
		if((--(ext->ref))==0){delete ext;}
		
		ptr = rhs.ptr;		
		ext = rhs.ext;
		++(ext->ref);

		return *this;
	}

	//////////////////////////////////////////////////////////////////////
	TPointer	operator->	(void) const {return static_cast<TPointer>(ptr);}
	TReference	operator*	(void) const {return *static_cast<TPointer>(ptr);}

	//////////////////////////////////////////////////////////////////////
	/*bool*/	operator NO_Boolean	(void)				 const {return (ptr?(ptr!=0):0);}
	NO_Boolean	operator!			(void)				 const {return (ptr?(!ptr):1);}
	NO_Boolean	operator<			(const Pointer& rhs) const {return ptr<static_cast<Type*>(rhs.ptr);}
	
	//////////////////////////////////////////////////////////////////////
	NO_Boolean	operator==	(const Pointer& rhs) const 
	{
		if(!ptr){return !rhs.ptr;}
		if(!(rhs.ptr)){return 0;}
		Type* rp = static_cast<Type*>(rhs.ptr);
		return ptr==rp;
	}

	//////////////////////////////////////////////////////////////////////
	NO_Boolean	operator!=	(const Pointer& rhs) const 
	{
		if(!ptr){return rhs.ptr!=0;}
		if(!(rhs.ptr)){return 1;}
		Type* rp = static_cast<Type*>(rhs.ptr);
		return ptr!=rp;
	}

	//////////////////////////////////////////////////////////////////////
	NO_Boolean	operator==	(const TPointer rhs) const 
	{
		if(!ptr){return !rhs;}
		if(!rhs){return 0;}
		return ptr==static_cast<Type*>(rhs);
	}
	
	//////////////////////////////////////////////////////////////////////
	NO_Boolean	operator!=	(const TPointer rhs) const 
	{
		if(!ptr){return rhs!=0;}
		if(!rhs){return 1;}
		return ptr!=static_cast<Type*>(rhs);
	}

	//////////////////////////////////////////////////////////////////////////
	Type* ptr;
	NO_IPtrHelp* ext;
};

//////////////////////////////////////////////////////////////////////////
template <class Target, class Source>
Target no_static_cast(Source rpSource)
{
    Source::TPointer pSource = NULL;
    Target::TPointer pTarget = static_cast<Target::TPointer>(pSource);
    pTarget;
    return Target(rpSource.ptr,rpSource.ext);
}

#endif 
